﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace M2B.GestionEntretiens.DAL
{
    /// <summary>
    /// Cette Classe décrit un répository qui se base sur entity framework
    /// </summary>
    /// <remarks>
    /// Informations de la classe : 
    /// <list type="bullet">
    /// <item name="authors">Auteur : M2B : Maher SAMMARI</item>
    /// <item name="creation date">Date de création : 01/04/2014</item>
    /// <item name="last modification">Date de dernière modification : 01/04/2014</item>
    /// </list>
    /// </remarks>
    public class EntityRepositoryBase<T> where T : class
    {

        /// <summary>
        /// Context
        /// </summary>
        private DbContext _dataContext;
        /// <summary>
        /// Interface pour l'entité
        /// </summary>
        private readonly IDbSet<T> _dbset;
        /// <summary>
        /// 
        /// </summary>
        private IQueryable<T> _query;

        #region Constructeur
        /// <summary>
        /// Constructeur ayant comme paramétre un data context 
        /// </summary>
        /// <param name="dataContext">Data context</param>
        public EntityRepositoryBase(DbContext dataContext)
        {
            this._dataContext = dataContext;
            this._dbset = _dataContext.Set<T>();
            _query = _dbset.AsQueryable();

        }
        #endregion

        #region Méthodes
        /// <summary>
        /// Ajout
        /// </summary>
        /// <param name="entity">Entity</param>
        public virtual void Add(T entity)
        {
            _dbset.Add(entity);

        }
        /// <summary>
        /// Mise à jour
        /// </summary>
        /// <param name="entity">Entity</param>
        public virtual void Update(T entity)
        {
            _dataContext.Entry(entity).State = EntityState.Modified;
        }
        /// <summary>
        /// Suppression
        /// </summary>
        /// <param name="entity">Entity</param>
        public virtual void Delete(T entity)
        {
            _dbset.Remove(entity);

        }
        /// <summary>
        /// Suppression selon prédicat
        /// </summary>
        /// <param name="predicate">Predicat</param>
        public virtual void Delete(Func<T, Boolean> predicate)
        {
            IEnumerable<T> objs = _dbset.Where<T>(predicate).AsEnumerable();
            foreach (T t in objs)
                _dbset.Remove(t);
        }
        /// <summary>
        /// Récupération d'une entité selon identificateur
        /// </summary>
        /// <param name="id">Identificateur</param>
        /// <returns>Entity</returns>
        public virtual T GetById(long id)
        {
            return _dbset.Find(id);

        }
        /// <summary>
        /// Récupération d'une entité selon une condition
        /// </summary>
        /// <param name="where">Condition</param>
        /// <param name="entityToEnclude">La liste des assocications à inclure</param>
        /// <returns>Entity</returns>
        public virtual T Get(Func<T, Boolean> where, string entityToEnclude = null)
        {
            if (!string.IsNullOrEmpty(entityToEnclude))
            {
                var associations = entityToEnclude.Split(' ');
                foreach (var item in associations)
                {
                    _query = _query.Include(item);
                }
                try
                {
                    return _query.Where(where).FirstOrDefault<T>();
                }
                catch (Exception e) { return _dbset.Where(where).FirstOrDefault<T>(); }
            }

            return _dbset.Where(where).FirstOrDefault<T>();

        }
        /// <summary>
        /// Récupération de tous les entités
        /// </summary>
        /// <param name="entityToEnclude">La liste des assocications à inclure</param>
        /// <returns>Entities</returns>
        public virtual IEnumerable<T> GetAll(string entityToEnclude = null)
        {
            if (!string.IsNullOrEmpty(entityToEnclude))
            {
                var associations = entityToEnclude.Split(' ');
                foreach (var item in associations)
                {
                    _query = _query.Include(item);
                }
                try
                {
                    return _query.ToList();
                }
                catch (Exception e) { return _dbset.ToList(); }
            }
            return _dbset.ToList();
        }
        /// <summary>
        /// Récupération d'une list d'entité selon une condition
        /// </summary>
        /// <param name="where"></param>
        /// <param name="entityToEnclude">La liste des assocications à inclure</param>
        /// <returns>Entities</returns>
        public virtual IEnumerable<T> GetMany(Func<T, bool> where, string entityToEnclude = null)
        {
            if (!string.IsNullOrEmpty(entityToEnclude))
            {
                var associations = entityToEnclude.Split(' ');
                foreach (var item in associations)
                {
                    _query = _query.Include(item);
                }
                try
                {
                    return _query.Where(where).ToList();
                }
                catch (Exception e) { return _dbset.ToList(); }
            }
            return _dbset.Where(where).ToList();

        }
        /// <summary>
        /// Sauvegarde
        /// </summary>
        public virtual void Save()
        {
            _dataContext.SaveChanges();

        }
        /// <summary>
        /// Déstruction
        /// </summary>
        /// <param name="disposing"></param>
        public virtual void Dispose(bool disposing)
        {
            if (_dataContext != null)
            {
                _dataContext.Dispose();
            }
        }


        #endregion


    }
}

